package net.yla.smartbus.module.ba.right.roles.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.vip.vjtools.vjkit.collection.ListUtil;
import com.vip.vjtools.vjkit.mapper.BeanMapper;
import net.yla.smartbus.core.api.RequestCode;
import net.yla.smartbus.core.base.BaseService;
import net.yla.smartbus.core.base.PageBean;
import net.yla.smartbus.core.constants.UserRoleEnum;
import net.yla.smartbus.core.exception.AppException;
import net.yla.smartbus.core.util.HttpClientUtil;
import net.yla.smartbus.core.util.PojoJsonUtil;
import net.yla.smartbus.core.util.RedisUtil;
import net.yla.smartbus.module.ba.log.form.UserLogForm;
import net.yla.smartbus.module.ba.log.serice.UserLogService;
import net.yla.smartbus.module.ba.right.admin.entity.AdminDO;
import net.yla.smartbus.module.ba.right.admin.mapper.AdminMapper;
import net.yla.smartbus.module.ba.right.login.dto.UserSession;
import net.yla.smartbus.module.ba.right.right.entity.RightsDO;
import net.yla.smartbus.module.ba.right.right.service.RightsService;
import net.yla.smartbus.module.ba.right.roleRL.entity.AdminRoleRL;
import net.yla.smartbus.module.ba.right.roleRL.mapper.RoleRLMapper;
import net.yla.smartbus.module.ba.right.roles.dto.RolesDto;
import net.yla.smartbus.module.ba.right.roles.entity.RolesDO;
import net.yla.smartbus.module.ba.right.roles.form.RoleForm;
import net.yla.smartbus.module.ba.right.roles.form.RolesForm;
import net.yla.smartbus.module.ba.right.roles.mapper.RolesMapper;
import net.yla.smartbus.module.ba.right.roles.query.QueryOfCount;
import net.yla.smartbus.module.ba.right.roles.query.QueryOfRoles;
import net.yla.smartbus.module.ba.right.roles.query.QueryOfView;
import net.yla.smartbus.module.ba.right.roles.service.RolesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Date: 2020-08-19 17:28
 * @Author: Being Nobody
 * @Version: 1.0
 */
@Service
public class RolesServiceImpl extends BaseService implements RolesService {

    @Resource
    private RolesMapper rolesMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private RoleRLMapper roleRLMapper;
    @Resource
    private RightsService rightsService;
    @Value("${erp.switch}")
    private String eSwitch;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserLogService userLogService;

    @Override
    public int deleteByPrimaryKey(Integer roleId) {
        return rolesMapper.deleteByPrimaryKey(roleId);
    }

    @Override
    public int insert(RolesDO record) {
        return rolesMapper.insert(record);
    }

    @Override
    public int insertSelective(RolesDO record) {
        return rolesMapper.insertSelective(record);
    }

    @Override
    public RolesDO selectByPrimaryKey(Integer roleId) {
        return rolesMapper.selectByPrimaryKey(roleId);
    }

    @Override
    public int updateByPrimaryKeySelective(RolesDO record) {
        return rolesMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(RolesDO record) {
        return rolesMapper.updateByPrimaryKey(record);
    }

    /**
     * 获取所有角色信息
     *
     * @param adminId
     * @return
     */
    @Override
    public List<RolesDO> roles(Integer adminId) {
        return rolesMapper.roles(adminId);
    }

    @Override
    public List<Integer> rolesAll(Integer adminId) {
        List<Integer> roleList = null;
        // 获取所有角色信息
        List<RolesDO> roles = this.roles(adminId);
        if (ListUtil.isNotEmpty(roles) && roles.size() > 0) {
            roleList = roles.stream().map(item -> item.getRoleId()).collect(Collectors.toList());
            if (ListUtil.isNotEmpty(roles) && roles.size() > 0) {
                for (RolesDO role : roles) {
                    this.fillChildren(role, roleList);
                }
            }
        }

        return roleList;
    }

    /**
     * 获取角色查询记录数
     *
     * @param queryOfCount
     * @return
     */
    @Override
    public int queryOfCount(QueryOfCount queryOfCount) {
        return rolesMapper.selectByName(queryOfCount);
    }

    /**
     * 角色集合
     *
     * @param queryOfRoles
     * @return
     */
    @Override
    public PageBean<List<JSONObject>> queryOfRoles(QueryOfRoles queryOfRoles) {
        String orderBy = super.orderBy(queryOfRoles.getSort(), queryOfRoles.getOrder());
        PageHelper.startPage(queryOfRoles.getPage(), queryOfRoles.getSize(), orderBy.isEmpty() ? "roleId desc" : orderBy);
        List<RolesDO> list = rolesMapper.selectByQuery(queryOfRoles);
        int index = (queryOfRoles.getPage() - 1) * queryOfRoles.getSize() + 1;
        PageInfo pageInfo = new PageInfo(list);
        List<JSONObject> result = this.pageOfRoles(list, queryOfRoles.getFields(), index);
        return new PageBean(result, queryOfRoles.getPage(), queryOfRoles.getSize(), (int) pageInfo.getTotal());
    }

    /**
     * 查看角色詳情
     *
     * @param queryOfView
     * @return
     */
    @Override
    public JSONObject rolesOfView(QueryOfView queryOfView) {
        RolesDO rolesDO = selectByPrimaryKey(queryOfView.getId());
        JSONObject result = null;
        if (rolesDO != null) {
            result = new JSONObject();
            result.put("id", rolesDO.getRoleId());
            result.put("name", rolesDO.getRoleName());
            result.put("remarks", rolesDO.getRemarks());
            result.put("inherits", rolesDO.getInherits());
            List<Byte> bytes = Arrays.asList(rolesDO.getMembers());
            result.put("members", bytes);
        }
        return result;
    }

    /**
     * 添加或更新角色信息
     *
     * @param rolesForm
     * @return
     */
    @Override
    public int save(RolesForm rolesForm) {
        // 校验是否已存在角色名
        RolesDO role = rolesMapper.role(rolesForm.getId(), rolesForm.getName());
        if (role != null) {
            throw new AppException("该角色名称已经存在", RequestCode.Operate_Tip);
        }
        // 校验参数
        if (rolesForm.getId() == null) {


            return this.addForm(rolesForm);
        }

        return this.updateForm(rolesForm);
    }

    /**
     * 逻辑删除
     *
     * @param query
     * @return
     */
    @Override
    @Transactional
    public int del(QueryOfView query) {
        if (query.getId() == null) {
            throw new AppException("角色ID不能为空", RequestCode.Form_Validate_Error);
        }
        RolesDO rolesDO = new RolesDO();
        rolesDO.setHidden(1);
        rolesDO.setRoleId(query.getId());
        RightsDO rightsDO = new RightsDO();
        rightsDO.setRoleId(query.getId());
        rightsDO.setHidden(1);
        int i = rightsService.updateByRoleId(query.getId());
        int i1 = rolesMapper.updateByPrimaryKeySelective(rolesDO);
        if (i + i1 <= 0) {
            throw new AppException("删除角色失败", RequestCode.Form_Validate_Error);
        }
        if(eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"role\",\"id\":" + query.getId() + ",\"action\":2}");
        }
        return 1;
    }

    /**
     * 添加所有菜单
     *
     * @param form
     * @return
     */
    @Override
    @Transactional
    public int add(RoleForm form) {
        form.setRoleId(null);
        // 表单校验
        this.validateForm(form);

        // 新增角色表
        RolesDO roleDO = BeanMapper.map(form, RolesDO.class);
        if (rolesMapper.insertSelective(roleDO) < 1) {
            throw new AppException("新增角色失败", RequestCode.Form_Validate_Error);
        }

        // 添加该角色拥有的权限信息
        this.addOrUpdateForm(roleDO.getRoleId(), form);
        if(eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"role\",\"id\":" + roleDO.getRoleId() + ",\"action\":0}");
        }
        return 1;
    }

    /**
     * 获取平台IDs
     *
     * @param form
     * @return
     */
    @Override
    public List<Integer> platformIds(RolesForm form) {
        if (ListUtil.isEmpty(form.getRoleIds()) || form.getRoleIds().size() < 1) {
            return null;
        }
        return rightsService.platformIds(form.getRoleIds());
    }

    /**
     * 角色IDs
     *
     * @param form
     * @return
     */
    @Override
    public List<Integer> menuIds(RolesForm form) {
        if (ListUtil.isEmpty(form.getRoleIds()) || form.getRoleIds().size() < 1) {
            return null;
        }
        return rightsService.menuIds(form.getRoleIds());
    }

    /**
     * 更新角色信息
     *
     * @param form
     * @return
     */
    @Override
    public int update(RoleForm form) {
        if (form.getRoleId() == null) {
            throw new AppException("角色id不能为空", RequestCode.Form_Validate_Error);
        }
        // 表单校验
        this.validateForm(form);
        // 新增角色表
        RolesDO roleDO = BeanMapper.map(form, RolesDO.class);
        if (rolesMapper.updateByPrimaryKeySelective(roleDO) < 1) {
            throw new AppException("更新角色失败", RequestCode.Form_Validate_Error);
        }
        System.out.println(roleDO);

        // 新增、修改二级方法，更新用户角色、角色平台、角色功能关系表
        this.addOrUpdateForm(roleDO.getRoleId(), form);
        if(eSwitch.equals(1)) {
            HttpClientUtil.sendDataErp("{\"table\":\"role\",\"id\":" + roleDO.getRoleId() + ",\"action\":1}");
        }
        return 1;
    }

    /**
     * 用户权限鉴定
     * @param userRoleEnum
     * @param token
     * @return
     */
    @Override
    public int userRoleEvaluation(UserRoleEnum userRoleEnum, String token,String ip) {
        if (token==null) {
            throw new AppException("请退出重新登录",RequestCode.forbid_error);
        }
        UserSession userSession = (UserSession) redisUtil.get(token);
        if (userSession==null){
            throw new AppException("请退出重新登录",RequestCode.forbid_error);
        }
        Integer menuId = rolesMapper.selectMenuId(userRoleEnum.getCode(), 5);
        if (menuId==null){
            throw new AppException("权限不足，请联系管理员",RequestCode.forbid_error);
        }
        Integer roleId = rolesMapper.selectUserRoleId(userSession.getAdminId());
        if (roleId==null){
            throw new AppException("权限不足，请联系管理员",RequestCode.forbid_error);
        }
        int roleMenuId = rolesMapper.selectRoleMenuId(roleId, menuId);
        if (roleMenuId==0){
            throw new AppException("权限不足，请联系管理员",RequestCode.forbid_error);
        }
        UserLogForm form = new UserLogForm();
        form.setAdminId(userSession.getAdminId());
        form.setIp(ip);
        form.setOp(userRoleEnum.getType());
        form.setName(userRoleEnum.getDesc());
        form.setDescription(userSession.getLoginId()+userRoleEnum.getDesc());
        form.setToken(token);
        int i = userLogService.addForm(form);
        System.out.println(ip+"hhhhhhh");
        return 1;
    }

    /**
     * 新增、修改二级方法，更新关系表
     */
    private void addOrUpdateForm(Integer roleId, RoleForm form) {

        // 删除角色平台中间表
        rightsService.deleteTrueByRoleId(roleId);

        // 如果表单中平台ids不为空，新增
        if (ListUtil.isNotEmpty(form.getPlatformIds()) && rightsService.addPlatformOfRole(roleId, form.getPlatformIds()) < 1) {
            throw new AppException("添加角色权限失败", RequestCode.Form_Validate_Error);
        }

        if (ListUtil.isNotEmpty(form.getMenuIds()) && rightsService.addMenuOfRole(roleId, form.getMenuIds()) < 1) {
            throw new AppException("更新角色关联功能失败", RequestCode.Form_Validate_Error);
        }

        //删除所有成员
        roleRLMapper.deleteAdminRoleRLByRoleId(form.getRoleId());

        //新增成员
        Byte[] members = form.getMembers();
        if (members != null && members.length != 0) {
            for (int i = 0; i < members.length; i++) {
                AdminRoleRL adminRoleRL = new AdminRoleRL();
                adminRoleRL.setAdminId((int) members[i]);
                adminRoleRL.setRoleId(roleId);
                roleRLMapper.insertAdminRoleRL(adminRoleRL);
            }
        }

        //更新成员数量
        RolesDO rolesDO = new RolesDO();
        rolesDO.setRoleId(roleId);
        rolesDO.setMemberCount(members != null && members.length != 0 ? members.length : 0);
        rolesDO.setMembers(members);
        rolesMapper.updateByPrimaryKeySelective(rolesDO);
    }


    private void validateForm(RoleForm form) {
        // 带上分组id，查询角色名称是否存在
        RolesDO roleDO = new RolesDO();
        roleDO.setRoleName(form.getRoleName());
        RolesDO roleDOS = rolesMapper.name(form.getRoleName());
        if (roleDOS != null && !roleDOS.getRoleId().equals(form.getRoleId())) {
            throw new AppException("角色名称已经存在", RequestCode.Form_Validate_Error);
        }
    }


    /**
     * 更新Form表单
     *
     * @param rolesForm
     * @return
     */
    private int updateForm(RolesForm rolesForm) {

        return rolesMapper.updateForm(rolesForm);
    }

    /**
     * 添加Form表单
     *
     * @param rolesForm
     * @return
     */
    private int addForm(RolesForm rolesForm) {
        return rolesMapper.insertForm(rolesForm);
    }

    private List<JSONObject> pageOfRoles(List<RolesDO> list, List<String> fields, int index) {
        List<JSONObject> result = null;
        List<Integer> accountIds = null;
        if (ListUtil.isNotEmpty(list)) {
            result = new ArrayList<>(list.size());
            for (int i = 0; i < list.size(); i++) {
                RolesDO rolesDO = list.get(i);
                JSONObject object = PojoJsonUtil.writeJsonByField(rolesDO, fields);
                object.put("index", index + i);
                // TODO 当前用户含有的角色
                List<AdminRoleRL> adminRoleRLs = roleRLMapper.selectByRoleId(rolesDO.getRoleId());
                if (ListUtil.isNotEmpty(adminRoleRLs)) {
                    accountIds = new ArrayList<>();
//                    adminIds
                    for (AdminRoleRL adminRoleRL : adminRoleRLs) {
                        AdminDO adminDO = adminMapper.selectByPrimaryKey(adminRoleRL.getAdminId());
                        if (adminDO != null) {
                            accountIds.add(adminDO.getAdminId());
                        }
                    }
                    object.put("accounts", accountIds);
                }
                result.add(object);
            }
        }



        return result;
    }

    private void fillChildren(RolesDO role, List<Integer> roleList) {
        for (int i = 0; i < role.getMembers().length; i++) {
            int member = role.getMembers()[i];
            if (!roleList.contains(member)) {
                roleList.add(member);
                RolesDO subRole = selectByPrimaryKey(member);
                if (subRole != null && subRole.getMembers() != null) {
                    fillChildren(subRole, roleList);
                }
            }
        }

    }

    @Override
    public List<RolesDto> selectByAdmin(QueryOfRoles queryOfRoles) {
        List<RolesDO> rolesDOS = rolesMapper.selectByAdmin(queryOfRoles);
        System.out.println(rolesDOS);
        List<RolesDto> rolesDtos = new ArrayList<>();
        RolesDto rolesDto = null;
        if (rolesDOS != null && rolesDOS.size() != 0) {
            for (RolesDO rolesDO : rolesDOS) {
                rolesDto = new RolesDto();
                rolesDto.setId(rolesDO.getRoleId());
                rolesDto.setMembers(rolesDO.getMembers());
                rolesDto.setApply(rolesDO.getApply());
                rolesDto.setName(rolesDO.getRoleName());
                rolesDto.setRemarks(rolesDO.getRemarks());
                rolesDto.setInherits(rolesDO.getInherits());
                rolesDto.setPlatformId(rolesDO.getPlatformId());
                rolesDto.setUniqueId(rolesDO.getUniqueId());
                rolesDto.setVersion(rolesDO.getVersion());
                rolesDto.setHidden(rolesDO.getHidden());
                rolesDto.setDisabled(rolesDO.getDisabled());
                rolesDto.setSortOrder(rolesDO.getSortOrder());
                rolesDto.setCreationTime(rolesDO.getCreationTime());
                rolesDto.setLastModifyTime(rolesDO.getLastModifyTime());
                rolesDto.setFlags(rolesDO.getFlags());
                rolesDtos.add(rolesDto);
            }
        }
        return rolesDtos;
    }

}
